package edu.msg.hrappy.backend.repository.beans;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceException;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

import edu.msg.hrappy.backend.model.AbstractModel;
import edu.msg.hrappy.backend.repository.BaseRepository;
import edu.msg.hrappy.backend.repository.exception.RepositoryException;


public class BaseRepositoryBean<T extends AbstractModel, I> implements
        BaseRepository<T, I> {

  //  private static final Logger LOG = LoggerFactory.getLogger(BaseRepositoryBean.class);
    private static final String GETALLMESSAGE = "GETALLMESSAGE";
    private static final String GETBYIDMESSAGE = "GETBYIDMESSAGE";
    private static final String INSERTMESSAGE = "INSERTMESSAGE";
    private static final String UPDATEMESSAGE = "UPDATEMESSAGE";
    private static final String DELETEMESSAGE = "DELETEMESSAGE";
    private final Class<T> clazz;
    @PersistenceContext(unitName = "project")
    private EntityManager manager;

    public BaseRepositoryBean(Class<T> clazz) {
        this.clazz = clazz;
    }

    public EntityManager getManager() {
        return manager;
    }

    @Override
    public List<T> getAll() {
        try {
            CriteriaBuilder cb = manager.getCriteriaBuilder();
            CriteriaQuery<T> criteriaQuery = cb.createQuery(clazz);
            Root<T> rootEntry = criteriaQuery.from(clazz);
            CriteriaQuery<T> all = criteriaQuery.select(rootEntry);
            TypedQuery<T> query = manager.createQuery(all);
//            manager.flush();
            return query.getResultList();
        } catch (final IllegalArgumentException | PersistenceException ex) {
       //     LOG.error(GETALLMESSAGE, ex);
            throw new RepositoryException(GETALLMESSAGE, ex);
        }
    }

    @Override
    public T getById(I id) {
        try {
            return manager.find(clazz, id);
        } catch (final IllegalArgumentException | PersistenceException ex) {
      //      LOG.error(GETBYIDMESSAGE, ex);
            throw new RepositoryException(GETBYIDMESSAGE, ex);
        }
    }

    @Override
    public void insert(T item) {
        try {
            manager.persist(item);
        } catch (final IllegalArgumentException | PersistenceException ex) {
      //      LOG.error(INSERTMESSAGE, ex);
            throw new RepositoryException(INSERTMESSAGE, ex);
        }
    }

    @Override
    public void update(T item) {
        try {
            manager.merge(item);
        } catch (final IllegalArgumentException | PersistenceException ex) {
      //      LOG.error(UPDATEMESSAGE, ex);
            throw new RepositoryException(UPDATEMESSAGE, ex);
        }
    }

    @Override
    public void delete(T item) {
        try {
            T toRemove = manager.merge(item);
            manager.remove(toRemove);
        } catch (final IllegalArgumentException | PersistenceException ex) {
    //        LOG.error(DELETEMESSAGE, ex);
            throw new RepositoryException(DELETEMESSAGE, ex);
        }
    }

}
